#include "CheckerBoard.h"

/**
 * the Constructor of ChessNode
 */
ChessNode::ChessNode() {
    Location = new int[2];
    PlayerID = -1;
    StepOrdinal = -1;
}

/**
 * Set the ChessNode
 * @param x ChessNode's Location X
 * @param y ChessNode's Location Y
 * @param playerid ChessNode's put Player
 * @param stepordinal the Ordinal of the step count
 */
void ChessNode::SetChess(int x, int y, int playerid, int stepordinal) {
    Location[0] = x; Location[1] = y;
    PlayerID = playerid; StepOrdinal = stepordinal;
}

/**
 * Set the ChessNode
 * @param location location array of the ChessNode: (x,y)
 * @param playerid ChessNode's put Player
 * @param stepordinal the Ordinal of the step count
 */
void ChessNode::SetChess(int *location, int playerid, int stepordinal) {
    Location[0] = location[0]; Location[1] = location[1];
    PlayerID = playerid; StepOrdinal = stepordinal;
}

/**
 * Set the Location of the ChessNode
 * @param x ChessNode's Location X
 * @param y ChessNode's Location Y
 */
void ChessNode::SetLocation(int x, int y) {
    Location[0] = x; Location[1] = y;
}

/**
 * Set the Location of the ChessNode
 * @param location array of the ChessNode
 */
void ChessNode::SetLocation(int *location) {
    Location[0] = location[0]; Location[1] = location[1];
}

/**
 * Set the PlayerID of the ChessNode
 * @param playerid ChessNode's put Player
 */
void ChessNode::SetPlayer(int playerid) {
    PlayerID = playerid;
}

/**
 * Set the StepOrdinal of the ChessNode
 * @param stepordinal the Ordinal of the step count
 */
void ChessNode::SetStep(int stepordinal) {
    StepOrdinal = stepordinal;
}

/**
 * return ChessNode's Location Array
 * @return ChessNode's Location Array
 */
int * ChessNode::LOCATION() {
    int *arr = new int[2];
    arr[0] = Location[0]; arr[1] = Location[1];
    return arr;
}

/**
 * return ChessNode's PlayerID
 * @return ChessNode's PlayerID
 */
int ChessNode::PLAYERID() {
    return PlayerID;
}

/**
 * return ChessNode's StepCount
 * @return ChessNode's StepCount
 */
int ChessNode::STEPORDINAL() {
    return StepOrdinal;
}

/*********************************************/

/**
 * the Constructor of ChessRoute
 */
ChessRoute::ChessRoute() {
    FirstPlayer = -1;
    NextPlayer = -1;
}

/**
 * Set the two Player
 * @param firstplayerid the first move player's id
 * @param nextplayerid the second move player's id
 */
void ChessRoute::SetPlayers(int firstplayerid, int nextplayerid) {
    FirstPlayer = firstplayerid; NextPlayer = nextplayerid;
}

/**
 * Add Step to the Route
 * @param Step the recent step's ChessNode
 */
void ChessRoute::AddStep(ChessNode Step) {
    Route.push(Step);
}

/**
 * return the Recently ChessNode which in the Route
 * @return the Recently ChessNode which in the Route
 */
ChessNode ChessRoute::RecentStep() {
    return Route.top();
}

/**
 * use PlayerId to check the Route
 * @return if correct, return true or return false
 */
bool ChessRoute::isChecked() {
    if (isEmpty()) {
        return true;
    }
    else {
        if (StepCount() % 2 == 1)
        {
            if (RecentStep().PLAYERID() == FirstPlayer){
                return true;
            }
            return false;
        }
        else
        {
            if (RecentStep().PLAYERID() == NextPlayer) {
                return true;
            }
            return false;
        }

    }
}

/**
 * to see the Route if empty
 * @return if the Route is empty, return true or return false
 */
bool ChessRoute::isEmpty() {
    return Route.empty();
}

/**
 * return the size for the Route
 * @return the size of the Route
 */
int ChessRoute::StepCount() {
    return Route.size();
}

/**
 * to show the player id of the first player
 * @return the player id of the first player
 */
int ChessRoute::showFirstPlayerID() {
    return FirstPlayer;
}

/**
 * to show the player id of the second player
 * @return the player id of the second player
 */
int ChessRoute::showNextPlayerID() {
    return NextPlayer;
}

/**
 * Delete the recently step in Route
 */
void ChessRoute::DelRecentStep() {
    Route.pop();
}

/**
 * Delete the recently two steps in Route
 */
void ChessRoute::DelTwoRecentStep() {
    Route.pop();
    Route.pop();
}


/*********************************************/

/**
 * the Constructor of CheckerBoard
 * @param size the Size of the CheckerBoard
 */
CheckerBoard::CheckerBoard(int size) {
    Size = size;
    Board = new ChessNode*[Size+2];
    for (int i = 0; i < Size+2; i++) {
        Board[i] = new ChessNode[Size+2];
    }
    for (int i = 1; i <= Size; i++) {
        for (int j = 1; j <= Size; j++) {
            Board[i][j].SetChess(i,j,-1,-1);
        }
    }
    Route.AddStep(Board[0][0]);
    Route.AddStep(Board[0][0]);
}

/**
 * the Constructor of CheckerBoard, doing nothing
 */
CheckerBoard::CheckerBoard() {

}

/**
 * Set the size of CheckerBoard(only using non-param constructor)
 * @param size the Size of the CheckerBoard
 */
void CheckerBoard::SetSize(int size) {
    Size = size;
    ReSetCheckerBoard();
}

/**
 * a private function which using in SetSize function
 */
void CheckerBoard::ReSetCheckerBoard() {
    Board = new ChessNode*[Size+2];
    for (int i = 0; i < Size+2; i++) {
        Board[i] = new ChessNode[Size+2];
    }
    for (int i = 1; i <= Size; i++) {
        for (int j = 1; j <= Size; j++) {
            Board[i][j].SetChess(i,j,-1,-1);
        }
    }
    Route.AddStep(Board[0][0]);
    Route.AddStep(Board[0][0]);
}

bool CheckerBoard::PlaceNode(int *location, int placeplayerid) {
    Board[location[0]][location[1]].SetStep(Route.RecentStep().STEPORDINAL()+1);
    Board[location[0]][location[1]].SetPlayer(placeplayerid);
    Route.AddStep(Board[location[0]][location[1]]);
    return Route.isChecked();
}

bool CheckerBoard::PlaceNode(int location_x, int location_y, int placeplayerid) {
    Board[location_x][location_y].SetStep(Route.RecentStep().STEPORDINAL()+1);
    Board[location_x][location_y].SetPlayer(placeplayerid);
    Route.AddStep(Board[location_x][location_y]);
    return Route.isChecked();
}

/*********************************************/
